home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-07  |  35.2 KB  |  1,583 lines

  1.  /* Main network program - provides both client and server functions */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include "global.h"
  7. #if (defined(__TURBOC__) || defined (__CPLUSPLUS)) && defined(MSDOS)
  8. #include <fcntl.h>
  9. #include <dos.h>
  10. #include <io.h>
  11. #include <conio.h>
  12. #include <ctype.h>
  13. #include <dir.h>
  14. #include <sys\stat.h>
  15. #endif
  16. #include "config.h"
  17. #ifdef    ANSIPROTO
  18. #include <stdarg.h>
  19. #endif
  20. #include "files.h"
  21. #include "mbuf.h"
  22. #include "socket.h"
  23. #include "iface.h"
  24. #include "ftpcli.h"
  25. #include "telnet.h"
  26. #include "remote.h"
  27. #include "session.h"
  28. #include "cmdparse.h"
  29. #include "ax25.h"
  30. #include "arp.h"
  31. #include "kiss.h"
  32. #include "enet.h"
  33. #include "timer.h"
  34. #include "proc.h"
  35. #include "tty.h"
  36. #include "daemon.h"
  37. #include "domain.h"
  38. #include "usock.h"
  39. #include "netrom.h"
  40. #include "ip.h"
  41. #include "tcp.h"
  42. #include "udp.h"
  43. #include "hardware.h"
  44. #include "commands.h"
  45. #include "asy.h"
  46. #include "trace.h"
  47. #ifdef DRSI
  48. #include "drsi.h"
  49. #endif
  50. #ifdef SCC
  51. #include "scc.h"
  52. #endif
  53. #ifdef VANESSA
  54. #include "vanessa.h"
  55. #endif
  56. #include "8250.h";
  57.  
  58. // unsigned int _stklen = 8192;
  59.  
  60. extern struct cmds Cmds[];
  61.  
  62. static char Escape = 0x1b;            /* default escape character is ESC */
  63.  
  64. char Badhost[] = "Unknown host %s\n";
  65. char Nospace[] = "No space\n";        /* Generic malloc fail message */
  66. char *Hostname = NULLCHAR;
  67. char *Rloguser = NULLCHAR;
  68. static FILE *Logfp;
  69. static struct proc *Cmdpp;
  70. struct proc *Display;
  71. struct session *Command, *Trace;
  72. static time_t StartTime;            /* Time that NOS was started */
  73. static int32 core ;
  74. int32 currtime = 0;
  75. char uploadstatus = 1;
  76. static int16 LWrap = 70;
  77. int Niface = 0;                        /* Number of Ifaces */
  78. #ifdef LZW
  79. int16 Lzwbits = 16;
  80. int Lzwmode = LZWCOMPACT;
  81. #endif
  82.  
  83. static void near loadfile __ARGS((void));
  84. static void savefile __ARGS((void));
  85. static struct timer Savetimer;
  86.  
  87. static void near doversion __ARGS((void));
  88.  
  89. #ifdef MSDOS
  90. #define    NORMALL    48
  91. #define NORMALH    23
  92. #define NORMALS 113
  93. #define INVERS    30
  94. #define    RED    71
  95. #define COMMON    7
  96. #define PANIC   206
  97.  
  98.  
  99.  
  100. static int normal = NORMALL;        /* used for statusline */
  101. static int normalh = NORMALH;
  102. static int normals = NORMALS;
  103. static int invers = INVERS;
  104. static int red = RED;
  105. static int common = COMMON;
  106. static int panic = PANIC;
  107. void statusline __ARGS((int i,void *v1,void *v2));
  108. static void dostatustimer __ARGS((void));
  109. struct timer Statustimer;
  110. static struct proc *statp;
  111. static unsigned char Currmode;
  112. #endif
  113.  
  114. #ifdef RESETTIMER
  115. /* Timer card - developed by DL3YDN.9203xx
  116.  * code is compiled in when defining RESETTIMER
  117.  *
  118.  * Register des Timers 8253
  119.  */
  120. #define TIMCTRL    0x213
  121. #define TIMER0    0x210
  122. #define TIMER1    0x211
  123. #define TIMER2    0x212
  124.  
  125. /* Register des I/O Bausteins 8255 */
  126. #define IOCTRL    0x217
  127. #define PORTA    0x214
  128. #define PORTB    0x215
  129. #define PORTC    0x216
  130.  
  131. static void inittim __ARGS((void));
  132. #endif
  133.  
  134. unsigned char Nrows = NROWS;    /* extra defined for 43/50 line mode - DB3FL */
  135.  
  136. static char Prompt[30];
  137.  
  138. int
  139. main(argc,argv)
  140. int argc;
  141. char *argv[];
  142. {
  143.     struct daemon *tp;
  144.     struct mbuf *bp;
  145.     int c, i;
  146.     char *startfile[3];
  147. #ifdef MSDOS
  148.     extern int Isat;
  149.     struct text_info r;
  150.  
  151.     gettextinfo(&r);
  152.     Currmode = r.currmode;
  153. #endif
  154.  
  155.     do {
  156.         c = getopt(argc,argv,"s:d:be");
  157.         switch(c){
  158.         case 's':    /* Number of sockets */
  159.             Nusock = atoi(optarg);
  160.             break;
  161.         case 'd':    /* Root directory for various files */
  162.             initroot(optarg);
  163.             break;
  164. #ifdef    __TURBOC__
  165.         case 'b':    /* Use BIOS for screen output */
  166.             directvideo = 0;
  167.             break;
  168. #endif
  169. #ifdef __CPLUSPLUS
  170. #ifdef MSDOS
  171.         case 'e':
  172.             textmode(C4350);
  173.             gettextinfo(&r);
  174.             break;
  175. #endif
  176. #endif
  177.         case '?':
  178.             puts("aborted...\007\r\n");
  179.             exit(1);
  180.         }
  181.     } while (c != EOF);
  182.  
  183. #ifdef MSDOS
  184.     Nrows = r.screenheight;
  185. #endif
  186.  
  187. #ifdef RESETTIMER
  188.     inittim();
  189. #endif
  190.  
  191.     if(getenv("TZ") == NULL)
  192.         putenv("TZ=GMT00");
  193.     tzset();
  194.  
  195.     StartTime = time(&StartTime);
  196.     currtime = time(NULL);
  197.  
  198.     kinit();
  199.     ipinit();
  200.     ioinit();
  201.     sockinit();
  202.     Cmdpp = mainproc("cmdintrp");
  203.  
  204.     window(1,3,80,Nrows);
  205.  
  206.     /*-------------------------------------------------------------------*
  207.     * initialize name cache DK5DC                                        *
  208.     *--------------------------------------------------------------------*/
  209.     cache = cxallocw(sizeof(Cache),(Dcache_size + 2));
  210.  
  211.     Sessions = (struct session *)cxallocw(Nsessions,sizeof(struct session));
  212.     Trace = newsession("Trace",TRACESESSION,1,0);
  213.     Lastcurr = Command = newsession("cmd interpreter",COMMAND,0,1);
  214.     Command->flowmode = Cooked;        /* set 'more' paging on command screen */
  215.     Trace->input = Command->input;
  216.     Display = newproc("display",512,display,0,NULLCHAR,NULL,0);
  217.  
  218.     /* allocates buffer for the trace screen */
  219.     swapscreen(Trace,NULLSESSION);
  220.  
  221.     /* This is a try to handle different machine speeds on startup.
  222.      * On various tests we learn that we need greater values on slow
  223.      * machines. The value of Isat reflects the type of the cpu. So
  224.      * its just easy to delay a longer time on a 8088 instead of a 386
  225.      * DC0HK/DB3FL.920416
  226.      */
  227. #ifdef MSDOS
  228.     c = Isat ? 200 : 1000;
  229. #else
  230.     c = 200;
  231. #endif
  232.  
  233.     /* Start background Daemons */
  234.     for(tp = Daemons; tp->name != NULLCHAR; tp++) {
  235.         newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
  236.         for(i = 0; i < c; i++) ;    /* machine dependend delay */
  237.     }
  238.  
  239.     dostatustimer();
  240.     doversion();
  241.     delay(0);
  242.  
  243.     startfile[1] = strxdup(optind < argc ? argv[optind] : Startup);
  244.     dosource(1,startfile,NULL);
  245.     xfree(startfile[1]);
  246.  
  247.     if(Niface)
  248.         loadfile();
  249.  
  250.     sprintf(Prompt,"%.27s> ",(Hostname != NULLCHAR) ? Hostname : "net");
  251.     tputs(Prompt);
  252.     usflush(Command->output);
  253.  
  254.     pwait(NULL);
  255.  
  256.     uploadstatus = 0;
  257.     core = availmem();
  258.  
  259.     /* Now loop forever, processing commands */
  260.     for(;;){
  261.         if(Current == Command && Command->flag) {    /* DK5DC */
  262.             usflush(Command->output);
  263.             tputs(Prompt);
  264.             Command->flag = 0;
  265.         }
  266.         if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
  267.             (void)cmdparse(Cmds,bp->data,Lastcurr);
  268.             free_p(bp);
  269.         }
  270.     }
  271. }
  272.  
  273. /* Keyboard input process */
  274. void
  275. keyboard(i,v1,v2)
  276. int i;
  277. void *v1;
  278. void *v2;
  279. {
  280.     int c, j, k;
  281.     struct mbuf *bp;
  282.     struct session *sp;
  283.  
  284.     /* Keyboard process loop */
  285.     for(;;){
  286.         if((c = kbread()) == Escape && Escape != 0)
  287.             c = -2;
  288.         if(c == -2 && Current != Command){
  289.             /* Save current tty mode and set cooked */
  290.             swapscreen(Current,Command);
  291.             Lastcurr = Current;
  292.             Current = Command;
  293.             if(Command->flag) {
  294.                 tputs(Prompt);
  295.                 Command->flag = 0;
  296.             }
  297.             /* set 'more' paging on command screen */
  298.             Command->flowmode = Cooked;
  299.         }
  300.  
  301.         if(c < -2)                 /* F1 to F10 pressed */
  302.             if(c == -13) {      /* ALT-F10 handled here */
  303.                 if (Current != Trace){
  304.                     swapscreen(Current,Trace);
  305.                     Lastcurr = Current;
  306.                     Current = Trace;
  307.                     Trace->flowmode = Raw;
  308.                 } else {
  309.                     swapscreen(Trace,Lastcurr);
  310.                     Current = Lastcurr;
  311.                     Lastcurr = Trace;
  312.                 }
  313.             } else {
  314.                 for(sp = Sessions, j = 1, k = abs(c); sp < &Sessions[Nsessions]; sp++) {
  315.                     if(sp->type == COMMAND)
  316.                         continue;
  317.                     j++;
  318.                     if(sp->type != FREE && j == k) {
  319.                         swapscreen(Current,sp);
  320.                         Lastcurr = Current;
  321.                         Current = sp;
  322.                         break;
  323.                     }
  324.                 }
  325.             }
  326.  
  327.         Current->row = (Current->split) ? Nrows - 5 : Nrows - 3;
  328.         psignal(&Current->row,1);
  329.         if(c >= 0){
  330.             /* If the screen driver was in morewait state, this char
  331.              * has woken him up. Toss it so it doesn't also get taken
  332.              * as normal input. If the char was a command escape,
  333.              * however, it will be accepted; this gives the user
  334.              * a way out of lengthy output.
  335.              */
  336.             if(!Current->morewait) {
  337.                 if((bp = ttydriv(Current,(char)c)) == NULLBUF){
  338.                     if(LWrap > 0 && Command != Current && c == 32
  339.                       && len_p(Current->ttystate.line) > LWrap) {
  340.                         bp = ttydriv(Current,13);
  341.                         send_mbuf(Current->input,bp,0,NULLCHAR,0);
  342.                     }
  343.                 } else {
  344.                     send_mbuf(Current->input,bp,0,NULLCHAR,0);
  345.                 }
  346.             }
  347.         }
  348.     }
  349. }
  350.  
  351. int
  352. dowrap(argc,argv,p)
  353. int argc;
  354. char *argv[];
  355. void *p;
  356. {
  357.     return setintrc(&LWrap,"Wrap",argc,argv,0,132);
  358. }
  359.  
  360. /* Standard commands called from main */
  361. int
  362. doexit(argc,argv,p)
  363. int argc;
  364. char *argv[];
  365. void *p;
  366. {
  367.     int i;
  368.  
  369. #ifdef RESETTIMER
  370.     outport(PORTC,0x00);  /* Disable Watchdog */
  371. #endif
  372.  
  373.     if(argc > 250) {
  374.         i = dirps();
  375.         iostop();
  376.         exit(argc);
  377.     }
  378.     reset_all();
  379.  
  380.     for(i = 0; i < 300; i++)
  381.         pwait(NULL);
  382.     shuttrace();
  383.     log(-1,"Shutdown %s", ctime(&currtime));
  384.     iostop();
  385.     fcloseall();
  386. #ifdef MSDOS
  387.     textmode((int)Currmode);        /* restore video mode */
  388. #endif
  389.     exit(0);
  390.     return 0;                        /* To satisfy lint */
  391. }
  392.  
  393. int
  394. dohostname(argc,argv,p)
  395. int argc;
  396. char *argv[];
  397. void *p;
  398. {
  399.     if(argc < 2 && Hostname != NULLCHAR)
  400.         tprintf("%s\n",Hostname);
  401.     else {
  402.         xfree(Hostname);
  403.         Hostname = strxdup(argv[1]);
  404.     }
  405.     return 0;
  406. }
  407.  
  408.  
  409. int
  410. dorloguser(argc,argv,p)
  411. int argc;
  412. char *argv[];
  413. void *p;
  414. {
  415.     if(argc < 2 && Rloguser != NULLCHAR)
  416.         tprintf("%s\n",Rloguser);
  417.     else {
  418.         xfree(Rloguser);
  419.         Rloguser = strxdup(argv[1]);
  420.     }
  421.     return 0;
  422. }
  423.  
  424. int
  425. dolog(argc,argv,p)
  426. int argc;
  427. char *argv[];
  428. void *p;
  429. {
  430.     static char *logname;
  431.  
  432.     if(argc < 2) {
  433.         if(Logfp != NULLFILE)
  434.             tprintf("Logging to %s\n",logname);
  435.         else
  436.             tputs("Logging off\n");
  437.     } else {
  438.         if(Logfp != NULLFILE) {
  439.             fclose(Logfp);
  440.             Logfp = NULLFILE;
  441.             if(logname != NULLCHAR)
  442.                 xfree(logname);
  443.             logname = NULLCHAR;
  444.         }
  445.         if(strcmp(argv[1],"off") != 0){
  446.             logname = strxdup(argv[1]);
  447.             if((Logfp = open_file(logname,APPEND_TEXT,0,1)) == NULLFILE)
  448.                 return -1;
  449.             log(-1,"Startup %s", ctime(&StartTime));
  450.         }
  451.     }
  452.     return 0;
  453. }
  454.  
  455. int
  456. dohelp(argc,argv,p)
  457. int argc;
  458. char *argv[];
  459. void *p;
  460. {
  461.     int i;
  462.     struct cmds *cmdp;
  463.  
  464.     tputs("Main commands:\n");
  465.     for(i = 0, cmdp = Cmds; cmdp->name != NULLCHAR; cmdp++)
  466.         if(strlen(cmdp->name) > 0) {
  467.             tprintf("%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
  468.             i = (i + 1) % 5;
  469.         }
  470.     if(i)
  471.         tputc('\n');
  472.     return 0;
  473.  
  474. }
  475.  
  476. /* Manipulate I/O device parameters */
  477. int
  478. doparam(argc,argv,p)
  479. int argc;
  480. char *argv[];
  481. void *p;
  482. {
  483.     register struct iface *ifp;
  484.  
  485.     if((ifp = if_lookup(argv[1])) == NULLIF){
  486.         tprintf(Badif,argv[1]);
  487.         return 1;
  488.     }
  489.     if(ifp->ioctl == NULLFP){
  490.         tputs("Not supported\n");
  491.         return 1;
  492.     }
  493.     /* Pass rest of args to device-specific code */
  494.     return (*ifp->ioctl)(ifp,argc-2,argv+2);
  495. }
  496.  
  497. #ifdef AX25
  498. /* Display or set IP interface control flags */
  499. int
  500. domode(argc,argv,p)
  501. int argc;
  502. char *argv[];
  503. void *p;
  504. {
  505.     struct arp_tab *arp, *ap;
  506.     char usage[] = "Usage: mode <host> [<datagram|vc|ipcam>]\n";
  507.     char buf1[AXBUF];
  508.     int32 addr;
  509.     int i;
  510.  
  511.     if(if_lookup(argv[1]) != NULLIF){
  512.         tputs(usage);
  513.         return -1;
  514.     }
  515.     if((addr = resolve(argv[1])) == 0 || (arp = arp_lookup(ARP_AX25,addr)) == NULLARP) {
  516.         tprintf(Badhost,argv[1]);
  517.         return -1;
  518.     }
  519.     if(argc < 3){
  520.         tprintf("%s (%s): Mode ",strupr(argv[1]),pax25(buf1,arp->hw_addr));
  521.         switch(arp->flags) {
  522.             case DATAGRAM_MODE:
  523.                 tputs("Datagram\n");
  524.                 break;
  525.             case CONNECT_MODE:
  526.                 tputs("VC\n");
  527.                 break;
  528.             case IPCAM_MODE:
  529.                 tputs("IPCAM\n");
  530.                 break;
  531.             default:
  532.                 tputs("unknown\n");
  533.                 break;
  534.         }
  535.         return 0;
  536.     }
  537.     switch(tolower(argv[2][0])){
  538.     case 'd':
  539.         arp->flags = DATAGRAM_MODE;
  540.         break;
  541.     case 'v':
  542.     case 'c':
  543.         arp->flags = CONNECT_MODE;
  544.         break;
  545.     case 'i':
  546.         arp->flags = IPCAM_MODE;
  547.         break;
  548.     default:
  549.         tputs(usage);
  550.         return -1;
  551.     }
  552.     for(i = 0; i < HASHMOD; i++){
  553.         for(ap = Arp_tab[i]; ap != (struct arp_tab *)NULL; ap = ap->next){
  554.             if(strcmp(arp->hw_addr,ap->hw_addr) == 0)
  555.                 ap->flags = arp->flags;
  556.         }
  557.     }
  558.     return 0;
  559. }
  560. #endif
  561.  
  562. int
  563. doescape(argc,argv,p)
  564. int argc;
  565. char *argv[];
  566. void *p;
  567. {
  568.     if(argc < 2) {
  569.         tputs("Escape char: ");
  570.         if(Escape < 32)
  571.             tprintf("CTRL-%c\n",Escape + 'A' - 1);
  572.         else
  573.             tprintf("%c\n",Escape);
  574.     } else
  575.         Escape = *argv[1];
  576.     return 0;
  577. }
  578.  
  579. /* Generate system command packet. Synopsis:
  580.  * remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
  581.  */
  582. int
  583. doremote(argc,argv,p)
  584. int argc;
  585. char *argv[];
  586. void *p;
  587. {
  588.     struct sockaddr_in fsock;
  589.     int s, c, klen;
  590.     char *data, *cmd, *host, x, *key = NULLCHAR;
  591.     int16 port, len = 1;
  592.     int32 addr = 0;
  593.  
  594.     port = IPPORT_REMOTE;    /* Set default */
  595.     optind = 1;        /* reinit getopt() */
  596.     while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
  597.         switch(c){
  598.         case 'a':
  599.             if((addr = resolve(optarg)) == 0){
  600.                 tprintf(Badhost,optarg);
  601.                 return -1;
  602.             }
  603.             break;
  604.         case 'p':
  605.             port = atoi(optarg);
  606.             break;
  607.         case 'k':
  608.             key = strxdup(optarg);
  609.             klen = strlen(key);
  610.             break;
  611.         case 's':
  612.             Rempass = strxdup(optarg);
  613.             return 0;    /* Only set local password */
  614.         }
  615.     }
  616.     if(optind > argc - 2){
  617.         tputs("Insufficient args\n");
  618.         return -1;
  619.     }
  620.     host = argv[optind++];
  621.     cmd = argv[optind];
  622.     if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
  623.         tputs(Nosocket);
  624.         return 1;
  625.     }
  626.     /* Did the user include a password or kickme target? */
  627.     if(addr != 0 && cmd[0] == 'k')
  628.         len += sizeof(int32);
  629.  
  630.     if(key != NULLCHAR && (cmd[0] == 'r' || cmd[0] == 'e'))
  631.         len += klen;
  632.  
  633.     if(len == 1)
  634.         data = &x;
  635.     else
  636.         data = mxallocw(len);
  637.  
  638.     fsock.sin_family = AF_INET;
  639.     if((fsock.sin_addr.s_addr = resolve(host)) == 0){
  640.         tprintf(Badhost,host);
  641.         goto cleanup;
  642.     }
  643.     fsock.sin_port = port;
  644.  
  645.     switch(cmd[0]){
  646.     case 'r':
  647.         data[0] = SYS_RESET;
  648.         if(key != NULLCHAR) {
  649.             strncpy(&data[1],key,klen);
  650.             data[data[1]+klen] = '\0';
  651.         }
  652.         break;
  653.     case 'e':
  654.         data[0] = SYS_EXIT;
  655.         if(key != NULLCHAR) {
  656.             strncpy(&data[1],key,klen);
  657.             data[data[1]+klen] = '\0';
  658.         }
  659.         break;
  660.     case 'k':
  661.         data[0] = KICK_ME;
  662.         if(addr != 0)
  663.             put32(&data[1],addr);
  664.         break;
  665.     default:
  666.         tprintf("Unknown command %s\n",cmd);
  667.         goto cleanup;
  668.     }
  669.     /* Form the command packet and send it */
  670.     if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1) {
  671.         tprintf("sendto failed: %s\n",sys_errlist[errno]);
  672.         goto cleanup;
  673.     }
  674. cleanup:
  675.     if(data != &x)
  676.         xfree(data);
  677.     if(key != NULLCHAR)
  678.         xfree(key);
  679.     close_s(s);
  680.     return 0;
  681. }
  682.  
  683. int
  684. domore(argc,argv,p)
  685. int argc;
  686. char *argv[];
  687. void *p;
  688. {
  689.     struct session *sp;
  690.     FILE *fp;
  691.     char buf[81];
  692.     int row = Nrows - 3;
  693.  
  694.     if((fp = open_file(argv[1],READ_TEXT,0,1)) == NULLFILE)
  695.         return -1;
  696.  
  697.     if((sp = newsession(argv[1],MORE,0,1)) == NULLSESSION) {
  698.         fclose(fp);
  699.         tputs(Nosess);
  700.         return -1;
  701.     }
  702.     /* Put tty into raw mode so single-char responses will work */
  703.     sp->ttystate.echo = sp->ttystate.edit = 0;
  704.  
  705.     while(fgets(buf,sizeof(buf),fp),!feof(fp)){
  706.         tputs(buf);
  707.         if(--row == 0){
  708.             row = keywait("--More--",0);
  709.             switch(row){
  710.             case -1:
  711.             case 'q':
  712.             case 'Q':
  713.                 goto done;
  714.             case '\n':
  715.             case '\r':
  716.                 row = 2;
  717.                 break;
  718.             case ' ':
  719.             default:
  720.                 row = Nrows - 3;
  721.             }
  722.         }
  723.     }
  724. done:
  725.     fclose(fp);
  726.     keywait(NULLCHAR,1);
  727.     freesession(sp);
  728.     return 0;
  729. }
  730.  
  731. int
  732. dotail(argc,argv,p)
  733. int argc;
  734. char *argv[];
  735. void *p;
  736. {
  737.     int handle, i;
  738.     unsigned line = 0, rdsize = 2000;
  739.     long length;
  740.     char buffer[2000], Noread[] = "Can't read %s: %s\n";
  741.  
  742.     if ((handle = open(argv[1],O_BINARY | O_RDONLY)) == -1) {
  743.         tprintf(Noread,argv[1],sys_errlist[errno]);
  744.         return -1;
  745.     }
  746.     length = filelength(handle);
  747.  
  748.     if (length > 2000) {
  749.         length -= 2000;
  750.     } else {
  751.         rdsize = (int)length;
  752.         length = 0;
  753.     }
  754.  
  755.     lseek (handle, length, SEEK_SET);
  756.     if (read (handle, buffer, rdsize) == -1) {
  757.         tprintf(Noread,argv[1],sys_errlist[errno]);
  758.         close(handle);
  759.         return -1;
  760.     }
  761.  
  762.     for (i = rdsize - 1; i > 0; i--) {
  763.         if (buffer[i] == '\n')
  764.             line++;
  765.         if (line == 18)
  766.             break;
  767.     }
  768.     for (; i < rdsize; i++)
  769.         tputc(buffer[i]);
  770.  
  771.     tputs("\n");
  772.     close(handle);
  773.     return 0;
  774. }
  775.  
  776. /* Log messages of the form
  777.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  778.  */
  779. #if    defined(ANSIPROTO)
  780. void
  781. log(int s,char *fmt, ...)
  782. {
  783.     va_list ap;
  784.     char *cp;
  785.     long t;
  786.     int i;
  787. #ifdef MSDOS
  788.     int fd;
  789. #endif
  790.     struct sockaddr fsocket;
  791.  
  792.     if(Logfp == NULLFILE)
  793.         return;
  794.  
  795.     time(&t);
  796.     cp = ctime(&t);
  797.     rip(cp);
  798.     i = SOCKSIZE;
  799.     fprintf(Logfp,"%s",cp);
  800.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  801.         fprintf(Logfp," %s",psocket(&fsocket));
  802.  
  803.     fprintf(Logfp," - ");
  804.     va_start(ap,fmt);
  805.     vfprintf(Logfp,fmt,ap);
  806.     va_end(ap);
  807.     fprintf(Logfp,"\n");
  808.     fflush(Logfp);
  809. #ifdef    MSDOS
  810.     /* MS-DOS doesn't really flush files until they're closed */
  811.     fd = fileno(Logfp);
  812.     if((fd = dup(fd)) != -1)
  813.         close(fd);
  814. #endif
  815. }
  816. #else
  817. /*VARARGS2*/
  818. void
  819. log(s,fmt,arg1,arg2,arg3,arg4,arg5)
  820. int s;
  821. char *fmt;
  822. int arg1,arg2,arg3,arg4,arg5;
  823. {
  824.     char *cp;
  825.     long t;
  826.     int i;
  827. #ifdef MSDOS
  828.     int fd;
  829. #endif
  830.     struct sockaddr fsocket;
  831.  
  832.     if(Logfp == NULLFILE)
  833.         return;
  834.  
  835.     time(&t);
  836.     cp = ctime(&t);
  837.     rip(cp);
  838.     i = SOCKSIZE;
  839.     fprintf(Logfp,"%s",cp);
  840.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  841.         fprintf(Logfp," %s",psocket(&fsocket));
  842.  
  843.     fprintf(Logfp," - ");
  844.     fprintf(Logfp,fmt,arg1,arg2,arg3,arg4,arg5);
  845.     fprintf(Logfp,"\n");
  846.     fflush(Logfp);
  847. #ifdef    MSDOS
  848.     /* MS-DOS doesn't really flush files until they're closed */
  849.     fd = fileno(Logfp);
  850.     if((fd = dup(fd)) != -1)
  851.         close(fd);
  852. #endif
  853. }
  854. #endif
  855.  
  856. int
  857. dosource(argc,argv,p)
  858. int argc;
  859. char *argv[];
  860. void *p;
  861. {
  862.     int linenum = 0;
  863.     char inbuf[BUFSIZ], intmp[BUFSIZ];
  864.     FILE *fp;
  865.  
  866.     /* Read command source file */
  867.     if((fp = open_file(argv[1],READ_TEXT,0,1)) == NULLFILE)
  868.         return -1;
  869.  
  870.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  871.         strcpy(intmp,inbuf);
  872.         linenum++;
  873.         if(cmdparse(Cmds,inbuf,NULL) != 0) {
  874.             tprintf("ERROR - line %d:\n%s\n",linenum,intmp);
  875.         }
  876.     }
  877.     fclose(fp);
  878.     return 0;
  879. }
  880.  
  881. #ifdef    __TURBOC__
  882. static int near dofstat __ARGS((void));
  883. #endif
  884.  
  885. int
  886. dostatus(argc,argv,p)
  887. int argc;
  888. char *argv[];
  889. void *p;
  890.  
  891. {
  892. extern unsigned char _osmajor;
  893. extern unsigned char _osminor;
  894.  
  895.     doversion();
  896.     tprintf("System time     : %s", ctime(&currtime));
  897.     tprintf("Start time      : %s", ctime(&StartTime));
  898.     tprintf("Elapsed time    : %s\n",tformat(secclock()));
  899.     tprintf("Startup coreleft: %lu\n",core);
  900.     tprintf("Coreleft now    : %lu\n",availmem());
  901.     if (_osmajor == 20){
  902.     tprintf("System          : OS/2 2.%d\n\n",_osminor);
  903. }else{
  904.     tprintf("DOS Vers.       : %d.%d\n\n",_osmajor,_osminor);
  905. }
  906.     if(argc < 9) {
  907. #ifdef    MSDOS
  908.         tprintf("Load info   : CodeSeg=%04x, DataSeg=%04x\n\n", _CS, _DS);
  909. #endif
  910. #ifdef    __TURBOC__
  911.         dofstat();        /* print status of open files */
  912. #endif
  913.     }
  914.     return 0;
  915. }
  916.  
  917. #ifdef    __TURBOC__
  918. /*
  919.  * Fstat utility code.
  920.  * Converted to go into NOS by Kelvin Hill - G1EMM  April 9, 1990
  921.  */
  922.  
  923. // extern unsigned char _osmajor;
  924. // extern unsigned char _osminor;
  925. static char * near localcopy(char far *);
  926. static char * near progname(unsigned int);
  927.  
  928. static int near
  929. dofstat()
  930. {
  931.     union REGS regs;
  932.     struct SREGS segregs;
  933.     char far *pfiletab, far * pnext;
  934.     char far *name, file[13], far * plist, far * entry;
  935.     char ownername[9], ownerext[5];
  936.     int nfiles, i, numhandles, entrylen;
  937.     unsigned int access, devinfo, progpsp;
  938.     long length, offset;
  939.     int heading = 0;
  940.  
  941.     regs.h.ah = 0x52;    /* DOS list of lists */
  942.     intdosx(®s, ®s, &segregs);
  943.  
  944.     /* make a pointer to start of master list */
  945.     plist = (char far *) MK_FP(segregs.es, regs.x.bx);
  946.  
  947.     /* pointer to start of file table */
  948.     pfiletab = (char far *) MK_FP(*(int far *) (plist + 6), *(int far *) (plist + 4));
  949.  
  950.     switch (_osmajor) {
  951.     case 2:
  952.         entrylen = 40;    /* DOS 2.x */
  953.         break;
  954.     case 3:   /* DRDOS 6.0, too */
  955.         entrylen = 53;    /* DOS 3.x */
  956.         break;
  957.     case 4:
  958.     case 5:  /* DOS 5.0 */
  959.     case 6:  /* DOS 6.0 */
  960.         entrylen = 59;  /* DOS 4.x - I do not know what is in the
  961.                          * extra 6 bytes */
  962.         break;
  963.     case 20: /* OS/2 */
  964.         entrylen = 59;
  965.         break;
  966.     default:
  967.         return 1;
  968.     }
  969.  
  970.     for (;;) {
  971.         /* pointer to next file table */
  972.         pnext = (char far *) MK_FP(*(int far *) (pfiletab + 2), *(int far *) (pfiletab + 0));
  973.         nfiles = *(int far *) (pfiletab + 4);
  974.  #ifdef MDEBUG
  975.         tprintf("\nFile table at %Fp entries for %d files\n", pfiletab, nfiles);
  976.  #endif
  977.         for (i = 0; i < nfiles; i++) {
  978.             /* cycle through all files, quit when we reach an
  979.              * unused entry
  980.              */
  981.             entry = pfiletab + 6 + (i * entrylen);
  982.             if (_osmajor >= 3) {
  983.                 name = entry + 32;
  984.                 sprintf(file,"%.11s",localcopy(name));
  985.                 numhandles = *(int far *) (entry + 0);
  986.                 access = (int) *(char far *) (entry + 2);
  987.                 length = *(long far *) (entry + 17);
  988.                 offset = *(long far *) (entry + 21);
  989.                 devinfo = *(int far *) (entry + 5);
  990.                 progpsp = *(int far *) (entry + 49);
  991.             } else {
  992.                 name = entry + 4;
  993.                 sprintf(file,"%.11s",localcopy(name));
  994.                 numhandles = (int) *(char far *) (entry + 0);
  995.                 access = (int) *(char far *) (entry + 1);
  996.                 length = *(long far *) (entry + 19);
  997.                 offset = *(long far *) (entry + 36);
  998.                 devinfo = (int) *(char far *) (entry + 27);
  999.             }
  1000.             if ((strlen(file) > 0) && (numhandles > 0) && !(devinfo & 0x80)) {
  1001.                 if(!heading) {
  1002.                     tputs("open files     length   offset hnd acc  PSP device       type/owner\n");
  1003.                     heading++;        /* header now printed */
  1004.                 }
  1005.                 tprintf("%8.8s.%3.3s %8ld %8ld  %2d ",
  1006.                        file, &file[8], length, offset, numhandles);
  1007.                 switch (access) {
  1008.                 case 0:
  1009.                     tputs("r ");
  1010.                     break;
  1011.                 case 1:
  1012.                     tputs("w ");
  1013.                     break;
  1014.                 case 2:
  1015.                     tputs("rw");
  1016.                     break;
  1017.                 default:
  1018.                     tputs("  ");
  1019.                 }
  1020.                 tputs("  ");
  1021.                 if (_osmajor >= 3)
  1022.                     tprintf("%04X", progpsp);
  1023.                 else
  1024.                     tputs("----");
  1025.                 tprintf(" drive %c: ", 'A' + (devinfo & 0x1F));
  1026.                 if (devinfo & 0x8000)
  1027.                     tputs("(network) ");
  1028.                 if (_osmajor >= 3) {
  1029.                     /*
  1030.                      * only DOS 3+ can find out
  1031.                      * the name of the program
  1032.                      */
  1033.                     fnsplit(progname(progpsp), NULL, NULL, ownername, ownerext);
  1034.                     tprintf("   [%s%s]", strlwr(ownername), strlwr(ownerext));
  1035.                 }
  1036.                 tputs("\n");
  1037.             }
  1038.             if (strlen(file) == 0)
  1039.                 return 0;
  1040.         }
  1041.         pfiletab = pnext;
  1042.     }
  1043. }
  1044.  
  1045. /* Make a copy of a string pointed to by a far pointer */
  1046. static char * near
  1047. localcopy(s)
  1048. char far *s;
  1049. {
  1050.     static char localstring[255];
  1051.     char far *p = s;
  1052.     char *l = localstring;
  1053.     int i = 0;
  1054.  
  1055.     while (*p != NULL && i++ < 255) {
  1056.         *l++ = *p++;
  1057.     }
  1058.  
  1059.     *l = '\0';
  1060.     return (localstring);
  1061. }
  1062.  
  1063. /*
  1064.  * Return a near pointer to a character string with the full path name of the
  1065.  * program whose PSP is given in the argument.  If the argument is invalid,
  1066.  * this may return gibberish but I don't know how to tell Offset 0x2C in the
  1067.  * PSP in the segment address of the environment of a program.  Beyond the
  1068.  * last environment string is a null marker, a word count (usually 1), then
  1069.  * the full pathname of the owner of the environment This only works for DOS
  1070.  * 3+
  1071.  */
  1072. static char * near
  1073. progname(pid)
  1074. unsigned int pid;
  1075. {
  1076.     unsigned far *envsegptr;    /* Pointer to seg address of environment */
  1077.     char far *envptr;            /* Pointer to pid's environment     */
  1078.     unsigned far *envsizeptr;    /* Pointer to environment size */
  1079.     unsigned envsize;            /* Size of pid's environment */
  1080.     unsigned ppid;                /* Parent psp address */
  1081.  
  1082.     /* find the parent process psp at offset 0x16 of the psp */
  1083.     ppid = *(unsigned far *) MK_FP(pid, 0x16);
  1084.  
  1085.     /* find the environment at offset 2Ch of the psp */
  1086.     envsegptr = (unsigned far *) MK_FP(pid, 0x2C);
  1087.     envptr = (char far *) MK_FP(*envsegptr, 0);
  1088.  
  1089.     /*
  1090.      * Make a pointer that contains the size of the environment block.
  1091.      * Must point back one paragraph (to the environments MCB plus three
  1092.      * bytes forward (to the MCB block size field).
  1093.      */
  1094.     envsizeptr = (unsigned far *) MK_FP(*envsegptr - 1, 0x3);
  1095.     envsize = *envsizeptr * 16;    /* x 16 turns it into bytes */
  1096.  
  1097.     while (envsize > 0) {
  1098.         /* search for end of environment block, or NULL */
  1099.         while (--envsize && *envptr++);
  1100.  
  1101.         /*
  1102.          * Now check for another NULL immediately following the first
  1103.          * one located and a word count of 0001 following that.
  1104.          */
  1105.         if (!*envptr && *(unsigned far *) (envptr + 1) == 0x1) {
  1106.             envptr += 3;
  1107.             break;
  1108.         }
  1109.     }
  1110.     return (envsize > 0) ? localcopy(envptr) : (pid == ppid) ? "-shell-" : "unknown";
  1111. }
  1112. #endif
  1113.  
  1114. static void near
  1115. loadfile(void)
  1116. {
  1117.     FILE *fp;
  1118.     struct iface *ifp;
  1119.  
  1120. #ifdef NETROM
  1121.     extern int donrload __ARGS((void));
  1122.     extern int Nr_save;
  1123. #endif
  1124.  
  1125. /* loading of ip-routes */
  1126.     if ((fp = open_file(Iproutefile,READ_BINARY,0,1)) != NULLFILE) {
  1127.         struct ip_saverecord ipbuf;
  1128.  
  1129.         while(fread((char *)&ipbuf, sizeof(ipbuf), 1, fp)) {
  1130.             for(ifp = Ifaces; ifp; ifp = ifp->next) {
  1131.                 if(ifp->niface == ipbuf.niface)
  1132.                     break;
  1133.             }
  1134.             if(ifp != NULLIF) {
  1135.                 if (ipbuf.gateway == 0xffffffffL)
  1136.                     ipbuf.gateway = 0;
  1137.                 rt_add(ipbuf.target,ipbuf.bits,ipbuf.gateway,ifp,
  1138.                     ipbuf.metric,0,ipbuf.flags);
  1139.             }
  1140.         }
  1141.         fclose(fp);
  1142.     }
  1143.  
  1144. /* loading of arp-entries */
  1145.     if ((fp = open_file(Arproutefile,READ_BINARY,0,1)) != NULLFILE) {
  1146.         struct arp_tab *p;
  1147.         struct arp_saverecord arpbuf;
  1148.         char  hw_addr[MAXHWALEN];
  1149.  
  1150.         if(getc(fp) == ARP_FILE_VERSION) {        /* Version 3 required !!!! */
  1151.             while(fread((char *)&arpbuf, sizeof(arpbuf), 1, fp)) {
  1152.                 if (fread(hw_addr, arpbuf.hwalen, 1, fp)) {
  1153.                     if (arpbuf.hardware < NHWTYPES) {
  1154.                         if ((p = arp_add(arpbuf.ip_addr,arpbuf.hardware,
  1155.                           hw_addr,arpbuf.pub,arpbuf.flags)) != NULLARP) {
  1156.                             stop_timer(&p->timer);
  1157.                             set_timer(&p->timer,0L);
  1158.                         }
  1159.                     }
  1160.                 }
  1161.             }
  1162.         }
  1163.         fclose(fp);
  1164.     }
  1165.  
  1166. /* loading of ax25-routes */
  1167. #ifdef AX25
  1168.     if ((fp = open_file(Axroutefile,READ_BINARY,0,1)) != NULLFILE) {
  1169.         struct axroute_tab *rp;
  1170.         struct iface *ifptable[ASY_MAX
  1171. #ifdef SCC
  1172.            + MAXSCC
  1173. #endif
  1174. #ifdef VANESSA
  1175.             + VAN_MAX
  1176. #endif
  1177. #ifdef AXIP
  1178.                  + NAX25
  1179. #endif
  1180. #ifdef DRSI
  1181.                             + DRMAX
  1182. #endif
  1183.                      ];
  1184.  
  1185.         struct ax_saverecord axbuf;
  1186.  
  1187.         memset((char *) ifptable, 0, sizeof(ifptable));
  1188.  
  1189.         for (ifp = Ifaces; ifp; ifp = ifp->next) {
  1190.             if (ifp->output == ax_output)
  1191.                 ifptable[ifp->niface] = ifp;
  1192.         }
  1193.         while (fread((char *)&axbuf, sizeof(axbuf), 1, fp)) {
  1194.             if (axbuf.time + Axholdtime < currtime)
  1195.                 continue;
  1196.             rp = axroute_tabptr(&axbuf.call, 1);
  1197.             if (axbuf.digi.call[0])
  1198.                 rp->digi = axroute_tabptr(&axbuf.digi, 1);
  1199.             if (axbuf.dev >= 0 && axbuf.dev < Niface)
  1200.                 rp->ifp = ifptable[axbuf.dev];
  1201.             rp->time = axbuf.time;
  1202.         }
  1203.         fclose(fp);
  1204.     }
  1205. #endif
  1206. #ifdef NETROM
  1207.     if(Nr_save) donrload();
  1208. #endif
  1209. }
  1210.  
  1211. static void
  1212. savefile(void)
  1213. {
  1214.   FILE * fp;
  1215.   int  i;
  1216.  
  1217. #ifdef NETROM
  1218.     extern int donrsave __ARGS((void));
  1219.     extern int Nr_save;
  1220. #endif
  1221.  
  1222.   stop_timer(&Savetimer);
  1223.   if ((fp = open_file(Iproutetmp,WRITE_BINARY,0,1)) != NULLFILE) {
  1224.       struct route *rp;
  1225.       struct ip_saverecord buf;
  1226.       int bits;
  1227.  
  1228.       for(bits = 31; bits >= 0; bits--) {
  1229.         for(i=0;i<HASHMOD;i++){
  1230.           for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  1231.             if(rp->target == 0 || rp->flags >= 0x01) continue;
  1232.             buf.target = rp->target;
  1233.             buf.bits = rp->bits;
  1234.             buf.gateway = (rp->gateway != 0) ? rp->gateway : 0xffffffffL;
  1235.             buf.niface = rp->iface->niface;
  1236.             buf.metric = rp->metric;
  1237.             buf.flags = rp->flags;
  1238.             fwrite((char *)&buf,sizeof(buf),1,fp);
  1239.           }
  1240.         }
  1241.       }
  1242.       fflush(fp);
  1243.       fclose(fp);
  1244.       unlink(Iproutefile);
  1245.       rename(Iproutetmp,Iproutefile);
  1246.   }
  1247.  
  1248.   pwait(NULL);
  1249.   if ((fp = open_file(Arproutetmp,WRITE_BINARY,0,1)) != NULLFILE) {
  1250.       struct arp_saverecord buf;
  1251.       struct arp_tab *p;
  1252.  
  1253.       putc(ARP_FILE_VERSION, fp);
  1254.       for (i = 0; i < HASHMOD; i++) {
  1255.         for (p = Arp_tab[i]; p; p = p->next) {
  1256.           if (p->hw_addr && p->state == ARP_VALID) {
  1257.             buf.ip_addr = p->ip_addr;
  1258.             buf.hardware = p->hardware;
  1259.             buf.flags = p->flags;
  1260.             buf.hwalen = p->hwalen;
  1261.             buf.pub = p->pub;
  1262.             fwrite((char *) & buf, sizeof(buf), 1, fp);
  1263.             fwrite(p->hw_addr, p->hwalen, 1, fp);
  1264.           }
  1265.         }
  1266.       }
  1267.       fflush(fp);
  1268.       fclose(fp);
  1269.       unlink(Arproutefile);
  1270.       rename(Arproutetmp,Arproutefile);
  1271.   }
  1272.  
  1273.   pwait(NULL);
  1274.  
  1275. #ifdef AX25
  1276.   if ((fp = open_file(Axroutetmp,WRITE_BINARY,0,1)) != NULLFILE) {
  1277.       struct ax_saverecord buf;
  1278.       struct axroute_tab *rp, *lp;
  1279.  
  1280.       for (i = 0; i < AXROUTESIZE; i++) {
  1281.         for (lp = 0, rp = axroute_tab[i]; rp; ) {
  1282.           if (rp->time + Axholdtime >= currtime) {
  1283.             buf.call = rp->call;
  1284.             if (rp->digi)
  1285.               buf.digi = rp->digi->call;
  1286.             else
  1287.               buf.digi.call[0] = '\0';
  1288.             buf.dev = rp->ifp ? rp->ifp->niface : -1;
  1289.             buf.time = rp->time;
  1290.             fwrite((char *) &buf, sizeof(buf), 1, fp);
  1291.             lp = rp;
  1292.             rp = rp->next;
  1293.           } else if (lp) {
  1294.             lp->next = rp->next;
  1295.             xfree((char *) rp);
  1296.             rp = lp->next;
  1297.           } else {
  1298.             axroute_tab[i] = rp->next;
  1299.             xfree((char *) rp);
  1300.             rp = axroute_tab[i];
  1301.           }
  1302.         }
  1303.       }
  1304.       fflush(fp);
  1305.       fclose(fp);
  1306.       unlink(Axroutefile);
  1307.       rename(Axroutetmp,Axroutefile);
  1308.   }
  1309.  
  1310.   pwait(NULL);
  1311.  
  1312. #endif
  1313. #ifdef NETROM
  1314.   if(Nr_save) donrsave();
  1315. #endif
  1316.  
  1317.   start_timer(&Savetimer);
  1318. }
  1319.  
  1320. int
  1321. dosavefile(int argc,char *argv[],void *p)
  1322. {
  1323.     if(argc < 2) {
  1324.         tprintf("Save timer %lu/%lu s\n",
  1325.             read_timer(&Savetimer)/1000L,
  1326.             dur_timer(&Savetimer)/1000L);
  1327.     } else {
  1328.         stop_timer(&Savetimer) ;            /* in case it's already running */
  1329.         /* what to call on timeout */
  1330.         Savetimer.func = (void (*) __ARGS((void *))) savefile;
  1331.         Savetimer.arg = NULLCHAR;            /* dummy value */
  1332.         /* set timer duration */
  1333.         set_timer(&Savetimer,atol(argv[1]) * 1000L);
  1334.         start_timer(&Savetimer);            /* and fire it up */
  1335.     }
  1336.     return 0;
  1337. }
  1338.  
  1339. static void near
  1340. doversion(void)
  1341. {
  1342.     tprintf("\nKA9Q NOS based %s (%s)\n"
  1343.             "Copyright 1990/4 by Phil Karn (KA9Q), "
  1344.             "WAMPES parts by DK5SG, and others.\n"
  1345.                         "Credits: DB3FL DC0HK DG1ZX DL1BKE DL6ZBA DL8YQ G6DHU GM8SAU \n\n",
  1346.             Version,__DATE__);
  1347.  
  1348. }
  1349.  
  1350. int
  1351. doattribute(argc,argv,p)
  1352. int argc;
  1353. char *argv[];
  1354. void *p;
  1355. {
  1356.     if(tolower(*argv[1] == 'm')) {
  1357.         normal = 112;
  1358.         normalh = 15;
  1359.         normals = 112;
  1360.         invers = 240;
  1361.         red = 127;
  1362.         common = 7;
  1363.         panic = 143;
  1364.     } else {
  1365.         normal = NORMALL;
  1366.         normalh = NORMALH;
  1367.         normals = NORMALS;
  1368.         invers = INVERS;
  1369.         red = RED;
  1370.         common = COMMON;
  1371.         panic = PANIC;
  1372.     }
  1373.     return 0;
  1374. }
  1375.  
  1376. #ifdef RESETTIMER
  1377. static void
  1378. inittim()
  1379. {
  1380.     outport(TIMCTRL,0x36); /*Init Timer0 for sqarewavegeneration*/
  1381.     outport(TIMER0,0x50);
  1382.     outport(TIMER0,0x50); /*Teilerfaktor für Timer0 0xffff*/
  1383.  
  1384.     outport(TIMCTRL,0x78); /*Init Timer1 for squarewavegeneration*/
  1385.     outport(TIMER1,0xff);
  1386.     outport(TIMER1,0x0d);
  1387.  
  1388.     outport(TIMCTRL,0xb4); /*Init Timer2 for sqarewavegeneration*/
  1389.     outport(TIMER2,0xff);
  1390.     outport(TIMER2,0x20);
  1391.  
  1392.  
  1393.     outport(IOCTRL,0x80); /*Set all I/O-Ports to output im Mode0*/
  1394.     outport(IOCTRL,0x80);
  1395.     outport(PORTC,0xff); /*activate Reset*/
  1396.  
  1397.     return;
  1398. }
  1399. #endif
  1400.  
  1401. static void
  1402. dostatustimer(void)
  1403. {
  1404.    if (!istate())   {                   /* return if in critical section*/
  1405.       start_timer(&Statustimer);
  1406.       return;
  1407.    }
  1408.    alert(statp,(void *)1);                /* wake process                 */
  1409. }
  1410.  
  1411. void
  1412. statusline(i,v1,v2)
  1413. int i;
  1414. void *v1;
  1415. void *v2;
  1416. {
  1417.     struct text_info str;
  1418.     struct time sttime;
  1419.     struct session *sp;
  1420.     struct usock *up;
  1421.     int s;
  1422.     char size;
  1423.     extern int Attended;
  1424.  
  1425.     statp = Curproc;                /* preserve process descriptor  */
  1426.     Statustimer.func = (void (*)())dostatustimer; /* what to call on timeout*/
  1427.     Statustimer.arg = NULLCHAR;     /* dummy value                  */
  1428.     set_timer(&Statustimer,990);    /* set timer duration, appr. 1 sec*/
  1429.  
  1430. #ifdef MDEBUG
  1431.     strcpy(Statustimer.tname,"Status");
  1432. #endif
  1433.     start_timer(&Statustimer);
  1434.  
  1435.     for(;;) {
  1436.         pwait(&sttime);
  1437.         stop_timer(&Statustimer);
  1438.         time(&currtime);
  1439.         gettime(&sttime);
  1440.  
  1441. #ifdef RESETTIMER
  1442.         outport(TIMER1,0xff);   /* Reset Timer */
  1443.         outport(TIMER1,0x0d);
  1444. #endif
  1445.  
  1446.         gettextinfo(&str);
  1447.         window(1,1,80,2);
  1448.         gotoxy(1,1);
  1449.  
  1450.         if((size = (availmem() < Memthresh * 2)) != 0) {
  1451.             textattr(panic);
  1452.             cputs(" PANIC ");
  1453.         } else {
  1454.             textattr(red);
  1455.             cputs(" W-NOS ");
  1456.             textattr(normal);
  1457.         }
  1458.  
  1459.         if(Current->type == COMMAND || Current->type == TRACESESSION || size) {
  1460.             cprintf(" Coreleft%7lu",availmem());
  1461.         } else {
  1462.             cprintf(" %-15.15s",Current->name);
  1463.         }
  1464.         s = -1;
  1465.         cprintf("│%-8s",(Current->type == FTP
  1466.           && (s = Current->cb.ftp->data) != -1)
  1467.           ? "FTP-DATA" : Sestypes[Current->type]);
  1468.  
  1469.         if((up = itop((s == -1) ? Current->s : s)) != NULLUSOCK) {
  1470.             switch(up->type) {
  1471.             case TYPE_NETROML4:
  1472.                 if(up->cb.nr4 != NULLNR4CB) {
  1473.                     cprintf("│Retries%3d│Unack%5d│SRTT%7ld│%s",
  1474.                         up->cb.nr4->blevel,up->cb.nr4->nbuffered,
  1475.                         up->cb.nr4->srtt,up->cb.nr4->choked ? "CHK" : "   ");
  1476.                 } else
  1477.                     goto line;
  1478.                 break;
  1479.             case TYPE_RAW:      /* fix to bad status line */
  1480.                 goto line;      /* in ping session */
  1481.         case TYPE_AX25I:
  1482.                 if(up->cb.ax25 != NULLAX25) { /* DAMA-changes zba940615 */
  1483.                     cprintf("│Retries%3d│Unack%5d│",
  1484.                         up->cb.ax25->retries,up->cb.ax25->unack);
  1485.                     if( up->cb.ax25->dama ) {
  1486.                         cprintf("DAMA-Tx%4d", len_p(up->cb.ax25->txq));
  1487.                     } else {
  1488.                         cputs("T1  ");
  1489.                         switch(up->cb.ax25->t1.state) {
  1490.                             case TIMER_RUN:
  1491.                                 cprintf("%3lu",read_timer(&up->cb.ax25->t1)/1000);
  1492.                                 break;
  1493.                             case TIMER_STOP:
  1494.                                 cputs("  -");
  1495.                                 break;
  1496.                             case TIMER_EXPIRE:
  1497.                                 cputs("  E");
  1498.                                 break;
  1499.                         }
  1500.                         cprintf("/%3lu",dur_timer(&up->cb.ax25->t1)/1000);
  1501.                     }
  1502.                     /*cprintf("/%3lu│%s",
  1503.                         dur_timer(&up->cb.ax25->t1)/1000,
  1504.                         up->cb.ax25->remotebusy ? "RNR" : "   ");*/
  1505.                     cprintf("│%s", up->cb.ax25->remotebusy ? "RNR" : "   ");
  1506.                 } else
  1507.                     goto line;
  1508.                 break;
  1509.             case TYPE_TCP:
  1510.                 if(up->cb.tcb != NULLTCB) {
  1511.                     if(s == -1) {
  1512.                         cprintf("│Backoff%3u│TxQ%7u│RTT ",
  1513.                             up->cb.tcb->backoff,up->cb.tcb->sndcnt);
  1514.                     } else {
  1515.                         cprintf("│Rx%8lu│Tx%8lu│RTT ",
  1516.                             up->cb.tcb->rcv.nxt - up->cb.tcb->irs,
  1517.                             up->cb.tcb->snd.una - up->cb.tcb->iss);
  1518.                     }
  1519.                     switch(up->cb.tcb->timer.state) {
  1520.                     case TIMER_RUN:
  1521.                         cprintf("%3lu",read_timer(&up->cb.tcb->timer)/1000);
  1522.                         break;
  1523.                     case TIMER_STOP:
  1524.                         cputs("  -");
  1525.                         break;
  1526.                     case TIMER_EXPIRE:
  1527.                         cputs("  E");
  1528.                         break;
  1529.                     }
  1530.                     cprintf("/%3lu│   ",
  1531.                         dur_timer(&up->cb.tcb->timer)/1000);
  1532.                 } else
  1533.                     goto line;
  1534.                 break;
  1535.             }
  1536.         } else {
  1537. line:
  1538. /*
  1539.             cprintf("│%-10s│%26s",Attended ? "Attended" : "Unattended"," ");
  1540. */
  1541.             cprintf("%31sttended",Attended ? "  A" : "Una");
  1542.         }
  1543.  
  1544.         if(Current->rfile != NULLCHAR && sttime.ti_sec & 1)
  1545.             cputs("│R");
  1546.         else if(Current->ufile != NULLCHAR && !(sttime.ti_sec & 1))
  1547.             cputs("│U");
  1548.         else
  1549.             cputs("│ ");
  1550.  
  1551.         
  1552.         cputs("│");
  1553.         textattr(red);
  1554.         cprintf(" %02d%c%02d ",
  1555.             sttime.ti_hour,(sttime.ti_sec & 1) ? ' ' : ':',sttime.ti_min);
  1556.         textattr(normal);
  1557. /* 2nd line starts here */
  1558.         textattr(normals);
  1559.         for(sp = Sessions, s = 0; sp < &Sessions[Nsessions]; sp++){
  1560.             if(sp->type == COMMAND || sp->type == TRACESESSION)
  1561.                 continue;
  1562.             s++;
  1563.             if(sp->type != FREE) {
  1564.                 if(socklen(sp->output,1))
  1565.                     textattr(invers);
  1566.  
  1567.                 cprintf(" %d:%s%s%s ",
  1568.                     s,
  1569.                     (sp->rfile == NULLCHAR) ? "" : "R:",
  1570.                     (sp->ufile == NULLCHAR) ? "" : "U:",
  1571.                     sp->name);
  1572.  
  1573.                 textattr(normals);
  1574.             }
  1575.         }
  1576.         clreol();
  1577.         window(str.winleft,str.wintop,str.winright,str.winbottom);
  1578.         textattr(common);
  1579.         gotoxy(str.curx,str.cury);
  1580.         start_timer(&Statustimer);
  1581.     }
  1582. }
  1583.